﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Kortex.Communication_objs;
using Kortex.WallMgr;
using Kortex.Common;
using Kortex.Container;
using System.Threading;
using System.IO;
using Newtonsoft.Json;

namespace Kortex.WallManagerControl.RecorderControler
{
    public partial class RecoderControl : UserControl
    {
        WallManager mProducer = null;
        int Ident = 1;
        //Dictionary<int, Recorders_record> record_chain = new Dictionary<int, Recorders_record>();
        List<Recorders_record> record_chain = new List<Recorders_record>();
        List<ReqRespDebugInfo> transction_chain = new List<ReqRespDebugInfo>();
       
        
        public RecoderControl()
        {
            InitializeComponent();
        }

        public RecoderControl(WallManager producer)
        {
            InitializeComponent();
            mProducer = producer;
            addRightClickMenuForListBox();
        }
        private int getIdnet()
        {

            return Ident++;
        }

        public void RecoderControllerResponce(Cube_command_reqObj req, General_responce res)
        {

            if (req.requester_guy != cmd_requster.recoderControler)
            {
                Recorders_record obj = new Recorders_record(req, res);
                Monitor.Enter(record_chain);
                record_chain.Add(obj);
                total_records.Text = record_chain.Count.ToString();
                Commnd_listBox.Items.Add(req.cmdType.ToString());
                Monitor.Exit(record_chain);
                //update_transction_views(obj);
            }
        }


        private void listBox_mnuExecute_Click(object sender, EventArgs e)
        {
            int index = Commnd_listBox.SelectedIndex;
            record_chain[index].req.requester_guy = cmd_requster.recoderControler;
            mProducer.RecorderExcuteRequest(record_chain[index].req, record_chain[index].req.cmdType.ToString());

        }

        private void listBox_mnuCubeExecute_Click(object sender, EventArgs e)
        {
            int index = Commnd_listBox.SelectedIndex;
            record_chain[index].req.requester_guy = cmd_requster.recoderControler;
            mProducer.RecordControlCubeRequest(record_chain[index].req, record_chain[index].req.cmdType.ToString());

        }

        private void listBox_mnuWallExecute_Click(object sender, EventArgs e)
        {
            Monitor.Enter(record_chain);

            int index = Commnd_listBox.SelectedIndex;
            record_chain[index].req.requester_guy = cmd_requster.recoderControler;
            mProducer.RecordControlWallRequest(record_chain[index].req, record_chain[index].req.cmdType.ToString());
            
            Monitor.Exit(record_chain);
            
        }

        private void listBox_mnuDelete_Click(object sender, EventArgs e)
        {
            int index = Commnd_listBox.SelectedIndex;
            record_chain.RemoveAt(index);
            Commnd_listBox.Items.RemoveAt(index);
            total_records.Text = record_chain.Count.ToString();

        }
        private void Commnd_listBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 'd' || e.KeyChar == 'D')
            {
                int index = Commnd_listBox.SelectedIndex;
                if (index >= 0)
                {
                    record_chain.RemoveAt(index);
                    Commnd_listBox.Items.RemoveAt(index);
                    total_records.Text = record_chain.Count.ToString();
                }
            }

            if (e.KeyChar == 'e' || e.KeyChar == 'E')
            {
                int index = Commnd_listBox.SelectedIndex;
                if (index >= 0)
                {
                    record_chain[index].req.requester_guy = cmd_requster.recoderControler;
                    mProducer.RecorderExcuteRequest(record_chain[index].req, record_chain[index].req.cmdType.ToString());

                }
            }



        }

        private void ShowToRichbox(ReqRespDebugInfo obj)
        {
            if (obj.cmd_type == reqResType.type_req)
                RawJson_send_reseice_richBox_new.Text += ("-->| " + "Ip=" + obj.mIp + " | " + obj.mJson + " | Time=" + obj.Time.Hour + ":" + obj.Time.Minute + ":" + obj.Time.Second + "." + obj.Time.Millisecond + " | Col=" + obj.mCol + " | Row=" + obj.mRow + "\n");
            else if (obj.cmd_type == reqResType.type_res)
                RawJson_send_reseice_richBox_new.Text += ("<--| " + "Ip=" + obj.mIp + " | " + obj.mJson + " | Time=" + obj.Time.Hour + ":" + obj.Time.Minute + ":" + obj.Time.Second + "." + obj.Time.Millisecond + " | Col=" + obj.mCol + " | Row=" + obj.mRow + "\n");

        
        }
        public void update_transction_views(ReqRespDebugInfo obj)
        {
            /*Monitor.Enter(RawJson_send_reseice_richBox);
            if (obj.cmd_type == reqResType.type_req)
                RawJson_send_reseice_richBox.AppendText("-->| "  + "Ip=" + obj.mIp +" | "+ obj.mJson + " | Time=" + obj.Time.Hour + ":" + obj.Time.Minute + ":" + obj.Time.Second + "." + obj.Time.Millisecond + " | Col=" + obj.mCol + " | Row=" + obj.mRow + "\n");
            else if (obj.cmd_type == reqResType.type_res)
                RawJson_send_reseice_richBox.AppendText("<--| " + "Ip=" + obj.mIp + " | " + obj.mJson + " | Time=" + obj.Time.Hour + ":" + obj.Time.Minute + ":" + obj.Time.Second + "." + obj.Time.Millisecond + " | Col=" + obj.mCol + " | Row=" + obj.mRow + "\n");
            Monitor.Exit(RawJson_send_reseice_richBox);
            */
            Monitor.Enter(transction_chain);
            transction_chain.Add(obj);
            ShowToRichbox(obj);
                        
            Monitor.Exit(transction_chain);
           

        
        }
        private void loadRecordFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();

            if (openFileDialog1.FileName != "")
            {
                FileInfo MyFile = new FileInfo(openFileDialog1.FileName);
                if (MyFile.Exists)
                {
                    FileStream FStream = null;
                    FStream = File.OpenRead(openFileDialog1.FileName);
                    int count = 0;
                    byte[] Buff = new Byte[FStream.Length];
                    count = FStream.Read(Buff, 0, (Int32)FStream.Length);
                    FStream.Close();
                    for(int i=0;i<Buff.Length;i++)
                        if(Buff[i] == '|')
                            Buff[i] = (byte)'\n';

                    
                    string records = System.Text.ASCIIEncoding.ASCII.GetString(Buff);

                    
                    LoadReCords(records);

                }
            }

        }

        private void LoadReCords(string records)
        {
            int i;
            string[] Allrecords = records.Split("\n".ToCharArray());

            Cube_command_Serlizer_obj[] dummyRec = null;
            dummyRec = new Cube_command_Serlizer_obj[Allrecords.Length - 1];

            for (i = 0; i < dummyRec.Length ; i++)
                dummyRec[i] = JsonConvert.DeserializeObject<Cube_command_Serlizer_obj>(Allrecords[i]);

            record_chain.Clear();

            Monitor.Enter(record_chain);
            for (i = 0; i < dummyRec.Length; i++)
            {
                Cube_command_reqObj req_obj = new Cube_command_reqObj(dummyRec[i]);
                Recorders_record Recobj = new Recorders_record(req_obj, null);
                
                record_chain.Add(Recobj);
                total_records.Text = record_chain.Count.ToString();
                Commnd_listBox.Items.Add(req_obj.cmdType.ToString());
                
            }
            Monitor.Exit(record_chain);
        
        }

        #region string to Byte Array
        public static byte C2b(char c)
        {
            if ((int)c < 256) return (byte)c;
            throw new Exception("character overflows a byte");
        }
        public static byte[] S2b(string value)
        {
            byte[] buffer = new byte[value.Length];
            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = C2b(value[i]);
            }

            return buffer;
        }
        #endregion

        private void saveRecordsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
            byte[] NotapasNewline = new byte[2];

            NotapasNewline[0] = (byte)'\r';
            NotapasNewline[1] = (byte)'\n';

            if (saveFileDialog1.FileName != "")
            {
                //WallConfig_obj obj = new WallConfig_obj(ALLCubes);
                //string json = JsonConvert.SerializeObject(obj);
                FileStream FStream = null;
                FStream = File.OpenWrite(saveFileDialog1.FileName);
                FStream.Seek(0, SeekOrigin.Begin);

                for(int i=0;i<record_chain.Count;i++) //(Cube_command_reqObj obj in record_chain)
                {
                    Cube_command_Serlizer_obj obj = new Cube_command_Serlizer_obj(record_chain[i].req);
                    string json = JsonConvert.SerializeObject(obj);
                    FStream.Write(S2b(json), 0, json.Length);
                    //FStream.Write(S2b("|"), 0, 1);
                    FStream.Write(NotapasNewline, 0, 2);
                }

                FStream.Close();
            }
        }

        private void clearRecordsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Monitor.Enter(record_chain);
            record_chain.Clear();
            Commnd_listBox.Items.Clear();
            total_records.Text = record_chain.Count.ToString();
            Monitor.Exit(record_chain);

        }

        private void Run_cube_Click(object sender, EventArgs e)
        {
            Monitor.Enter(record_chain);
            for (int i = 0; i < int.Parse(Recorder_loopCount.Text);i++ )
                foreach (Recorders_record item in record_chain)
                {
                    item.req.requester_guy = cmd_requster.recoderControler;
                    mProducer.RecorderExcuteRequest(item.req, item.req.cmdType.ToString());
                }
            Monitor.Exit(record_chain);
           
        }

       

        private void Run_at_wall_Click(object sender, EventArgs e)
        {
           
            Monitor.Enter(record_chain);
            foreach (Recorders_record item in record_chain)
            {
                item.req.requester_guy = cmd_requster.recoderControler;
                mProducer.RecordControlWallRequest(item.req, item.req.cmdType.ToString());
            }
            Monitor.Exit(record_chain);
            
        }

        private void Transction_clear_but_Click(object sender, EventArgs e)
        {
            
            Monitor.Enter(transction_chain);
            transction_chain.Clear();
            RawJson_send_reseice_richBox_new.Clear();
            Monitor.Exit(transction_chain);
            
        }

        private void Recordds_clear_but_Click(object sender, EventArgs e)
        {
            clearRecordsToolStripMenuItem_Click(null, null);
        }

        private int checkDuplicate(Cube_command_reqObj reffObj, Cube_command_reqObj checkObj)
        {
            if (reffObj == checkObj) return 1;
            
            if (reffObj.args == null) return 1;

            if (reffObj.args.Length < 0) return 1;

            for (int i = 0; i < reffObj.args.Length; i++)
            {
                if (reffObj.args[i] != checkObj.args[i])
                    return 1;
            
            }

                return 0;
        }

        private void MarkDuplicate()
        {
            int i, j,ret;
            for (j = 0; j < record_chain.Count; j++)
            {

                for (i = 0; i < record_chain.Count; i++)
                {
                    if (record_chain[j].req.cmdType == record_chain[i].req.cmdType)
                    {
                        ret = checkDuplicate(record_chain[j].req, record_chain[i].req);
                        if (ret == 0)
                        {
                            record_chain[i].isDuplicate = true;
                            //record_chain.RemoveAt(i);

                            //Commnd_listBox.Items.RemoveAt(i);
                        }
                        else
                            record_chain[i].isDuplicate = false;



                    }

                }
            }
        
        }

        private void RemoveDuplicate()
        {
            bool KeepRuning = true;

            while (KeepRuning)
            {
                KeepRuning = false;
                for (int j = 0; j < record_chain.Count; j++)
                {
                    if (record_chain[j].isDuplicate)
                    {
                        record_chain.RemoveAt(j);
                       Commnd_listBox.Items.RemoveAt(j);
                       KeepRuning = true;
                       break;
                    }
                }
 
            
            }
        
        }

        private void removeDuplicateToolStripMenuItem_Click(object sender, EventArgs e)
        {
           
            Monitor.Enter(record_chain);

            MarkDuplicate();
            RemoveDuplicate();
            total_records.Text = record_chain.Count.ToString();
           

                Monitor.Exit(record_chain);

        }

        private void clearTransctionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Transction_clear_but_Click(null, null);
        }

        private void reLoadTransctionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Monitor.Enter(transction_chain);
            //transction_chain.Clear();
            RawJson_send_reseice_richBox_new.Clear();

            foreach(ReqRespDebugInfo obj in transction_chain)
            ShowToRichbox(obj);

            Monitor.Exit(transction_chain);

        }

        private void executeRecordsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Run_cube_Click(null, null);

        }

        private void Tree_transctions_Click(object sender, EventArgs e)
        {

        }

       

       

       
    }
}
